package com.liuhongwei.test.builder;

import com.liuhongwei.test.bean.Constants;
import com.liuhongwei.test.bean.FieldInfo;
import com.liuhongwei.test.bean.TableInfo;
import com.liuhongwei.test.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

public class BuildAssemble {

    private static final Logger log = LoggerFactory.getLogger(BuildAssemble.class);


    public static void execute(TableInfo tableInfo) {
        File folder = new File(Constants.PATH_ASSEMBLE);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        OutputStream os = null;
        OutputStreamWriter osw = null;
        BufferedWriter bw = null;
        try {
            String assembleName = StringUtils.upperCaseFirst(tableInfo.getBeanName()) + Constants.SUFFIX_ASSEMBLE;
            os = new FileOutputStream(folder + "/" + assembleName + ".java");
            osw = new OutputStreamWriter(os, "UTF-8");
            bw = new BufferedWriter(osw);

            bw.write("package " + Constants.PACKAGE_ASSEMBLE + ";\n\n");
            //写入Import
            writeImport(tableInfo, bw);
            //写入类注释
            BuildComment.createClassComment(bw, tableInfo.getComment() + "赋值工具");
            bw.write("public class " + assembleName + " {\n\n");
//            bw.write("public class " + tableInfo.getBeanParamName() + "  {\n\n");

            //写入属性
            writeField(tableInfo, bw);

            bw.write("}");
            bw.flush();
        } catch (Exception e) {
            log.error("创建query失败", e);
        } finally {
            BuildBase.close(os, osw, bw);
        }
    }


    private static void writeGetterSetter(List<FieldInfo> fieldList, BufferedWriter bw) throws IOException {
        for (FieldInfo fieldInfo : fieldList) {
            String javaType = fieldInfo.getJavaType();
            String propertyName = fieldInfo.getPropertyName();
            String tempField = StringUtils.upperCaseFirst(propertyName);
            bw.write("\tpublic void set" + tempField + "(" + javaType + " " + propertyName + ") {\n");
            bw.write("\t\tthis." + propertyName + " = " + propertyName + ";\n");
            bw.write("\t}\n");

            bw.write("\tpublic " + javaType + " get" + tempField + "() {\n");
            bw.write("\t\treturn " + propertyName + ";\n");
            bw.write("\t}\n\n");
        }
        bw.newLine();
    }

    private static void writeField(TableInfo tableInfo, BufferedWriter bw) throws Exception {

        String bean = StringUtils.lowerCaseFirst(tableInfo.getBeanName());
        String clazzBean = StringUtils.upperCaseFirst(tableInfo.getBeanName());
        String clazzQuery = clazzBean + Constants.SUFFIX_BEAN_QUERY;
        String beanQuery = StringUtils.lowerCaseFirst(clazzQuery);

        BuildComment.createFieldComment(bw, "JSON对象转查询对象");

        bw.write(String.format("\tpublic static %s toPageQuery(JSONObject jsonObject) {\n", clazzQuery));
        bw.write(String.format("\t\t%s %s = new %s();\n", clazzQuery, beanQuery, clazzQuery));
        bw.newLine();
        bw.write("\t\tInteger currentPage = jsonObject.getInteger(\"currentPage\");\n");
        bw.write("\t\tInteger pageSize = jsonObject.getInteger(\"pageSize\");\n");
        bw.write(String.format("\t\t%s.setCurrentPage(currentPage == null ? 1 : currentPage);\n", beanQuery));
        bw.write(String.format("\t\t%s.setPageSize(pageSize == null ? 15 : pageSize);\n", beanQuery));
        bw.newLine();
        // base
        ArrayList<FieldInfo> fieldInfos = new ArrayList<>(tableInfo.getFieldList());
        fieldInfos.addAll(tableInfo.getFieldExtendList());
        for (FieldInfo fieldInfo : fieldInfos) {
            String upperCaseFirst = StringUtils.upperCaseFirst(fieldInfo.getPropertyName());
            String lowerCaseFirst = StringUtils.lowerCaseFirst(fieldInfo.getPropertyName());
            if (fieldInfo.getJavaType().equals("Integer")) {
                bw.write(String.format("\t\t%s.set%s(jsonObject.getInteger(\"%s\"));\n", beanQuery, upperCaseFirst, lowerCaseFirst));
            } else if (fieldInfo.getJavaType().equals("Date")) {
                bw.write(String.format("\t\t%s.set%s(jsonObject.getDate(\"%s\"));\n", beanQuery, upperCaseFirst, lowerCaseFirst));
            } else {
                bw.write(String.format("\t\t%s.set%s(AppStringUtils.formatEmptyToNull(jsonObject.getString(\"%s\")));\n", beanQuery, upperCaseFirst, lowerCaseFirst));
            }
        }
        bw.write(String.format("\t\treturn %s;\n", beanQuery));
        bw.write("\t}\n");
        bw.newLine();


        BuildComment.createFieldComment(bw, "分页查询对象转JSON对象");
        bw.write(String.format("\tpublic static JSONObject toPageJSONObject(%s %s) {\n", clazzBean, bean));
        bw.write("\t\tJSONObject jsonObject = new JSONObject();\n");
        for (FieldInfo fieldInfo : tableInfo.getFieldList()) {
            String upperCaseFirst = StringUtils.upperCaseFirst(fieldInfo.getPropertyName());
            String lowerCaseFirst = StringUtils.lowerCaseFirst(fieldInfo.getPropertyName());
            bw.write(String.format("\t\tjsonObject.put(\"%s\", %s.get%s());\n", lowerCaseFirst, bean, upperCaseFirst));
        }
        bw.write("\t\treturn jsonObject;\n");
        bw.write("\t}\n");
        bw.newLine();

        BuildComment.createFieldComment(bw, "查询对象转JSON对象");
        bw.write(String.format("\tpublic static JSONObject toJSONObject(%s %s) {\n", clazzBean, bean));
        bw.write("\t\tJSONObject jsonObject = new JSONObject();\n");
        for (FieldInfo fieldInfo : tableInfo.getFieldList()) {
            String upperCaseFirst = StringUtils.upperCaseFirst(fieldInfo.getPropertyName());
            String lowerCaseFirst = StringUtils.lowerCaseFirst(fieldInfo.getPropertyName());
            bw.write(String.format("\t\tjsonObject.put(\"%s\", %s.get%s());\n", lowerCaseFirst, bean, upperCaseFirst));
        }
        bw.write("\t\treturn jsonObject;\n");
        bw.write("\t}\n");
        bw.newLine();


        BuildComment.createFieldComment(bw, "JSON对象转新增对象");
        bw.write(String.format("\tpublic static %s to%sInsert(JSONObject jsonObject) {\n", clazzBean, clazzBean));
        bw.write(String.format("\t\t%s %s = new %s();\n", clazzBean, bean, clazzBean));
        for (FieldInfo fieldInfo : tableInfo.getFieldList()) {
            String upperCaseFirst = StringUtils.upperCaseFirst(fieldInfo.getPropertyName());
            String lowerCaseFirst = StringUtils.lowerCaseFirst(fieldInfo.getPropertyName());

            if (lowerCaseFirst.equals("uuid")) {
                bw.write(String.format("\t\t%s.setUuid(CHUUIDUtils.generateUUID());\n", bean));
            } else if (fieldInfo.getJavaType().equals("Integer")) {
                bw.write(String.format("\t\t%s.set%s(jsonObject.getInteger(\"%s\"));\n", bean, upperCaseFirst, lowerCaseFirst));
            } else if (lowerCaseFirst.equals("createTime")) {
                bw.write(String.format("\t\t%s.set%s(new Date());\n", bean, upperCaseFirst));
            } else if (lowerCaseFirst.equals("updateTime")) {
                bw.write(String.format("\t\t%s.set%s(new Date());\n", bean, upperCaseFirst));
            } else if (fieldInfo.getJavaType().equals("Date")) {
                bw.write(String.format("\t\t%s.set%s(jsonObject.getDate(\"%s\"));\n", bean, upperCaseFirst, lowerCaseFirst));
            } else {
                bw.write(String.format("\t\t%s.set%s(AppStringUtils.formatEmptyToNull(jsonObject.getString(\"%s\")));\n", bean, upperCaseFirst, lowerCaseFirst));
            }
        }
        bw.write(String.format("\t\treturn %s;\n", bean));
        bw.write("\t}\n");
        bw.newLine();

        BuildComment.createFieldComment(bw, "JSON对象转更新对象");
        bw.write(String.format("\tpublic static %s to%sUpdate(JSONObject jsonObject) {\n", clazzBean, clazzBean));
        bw.write(String.format("\t\t%s %s = new %s();\n", clazzBean, bean, clazzBean));
        for (FieldInfo fieldInfo : tableInfo.getFieldList()) {
            String upperCaseFirst = StringUtils.upperCaseFirst(fieldInfo.getPropertyName());
            String lowerCaseFirst = StringUtils.lowerCaseFirst(fieldInfo.getPropertyName());
            if (fieldInfo.getJavaType().equals("Integer")) {
                bw.write(String.format("\t\t%s.set%s(jsonObject.getInteger(\"%s\"));\n", bean, upperCaseFirst, lowerCaseFirst));
            } else if (lowerCaseFirst.equals("createTime")) {
                //bw.write(String.format("\t\t%s.set%s(new Date());\n", bean, upperCaseFirst));
            } else if (lowerCaseFirst.equals("updateTime")) {
                bw.write(String.format("\t\t%s.set%s(new Date());\n", bean, upperCaseFirst));
            } else if (fieldInfo.getJavaType().equals("Date")) {
                bw.write(String.format("\t\t%s.set%s(jsonObject.getDate(\"%s\"));\n", bean, upperCaseFirst, lowerCaseFirst));
            } else {
                bw.write(String.format("\t\t%s.set%s(AppStringUtils.formatEmptyToNull(jsonObject.getString(\"%s\")));\n", bean, upperCaseFirst, lowerCaseFirst));
            }
        }
        bw.write(String.format("\t\treturn %s;\n", bean));
        bw.write("\t}\n");
        bw.newLine();

    }


    private static void writeImport(TableInfo tableInfo, BufferedWriter bw) throws IOException {
        if (tableInfo.getHaveBigDecimal()) {
            bw.write("import java.math.BigDecimal;\n");
        }
        if (tableInfo.getHaveDate() || tableInfo.getHaveDateTime()) {
            bw.write("import java.util.Date;\n");
        }

        bw.write("import com.alibaba.fastjson.JSONObject;\n");
        bw.write("import com.liuhongwei.test.utils.CHUUIDUtils;\n");
        bw.write("import com.liuhongwei.test.utils.AppStringUtils;\n");
        bw.write("import " + Constants.PACKAGE_PO + "." + tableInfo.getBeanName() + ";\n");
        bw.write("import " + Constants.PACKAGE_QUERY + "." + tableInfo.getBeanName() + Constants.SUFFIX_BEAN_QUERY + ";\n");


    }

    public static void main(String[] args) {
        List<TableInfo> tableInfoList = BuildTable.getTable();
        for (TableInfo tableInfo : tableInfoList) {
            BuildAssemble.execute(tableInfo);
        }
    }

}
